using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Media;
using ProtoGame.GameLib;
using ProtoGame.RegioesGatilho;
using ProtoGame.GameLib.GameComponents;
using ProtoGame.Sprites;


namespace ProtoGame.Fases.Fantasma
{
    /// <summary>
    /// This is a game component that implements IUpdateable.
    /// </summary>
    public class PGFantasmaMain<TIdFase> : PGFase<TIdFase> where TIdFase : struct
    {
        enum TiposSaidas
        {
            Volta,
            Proxima
        }

        const int qtdeSalas = 6;

        List<EntityManager> fase;
        int iteraSalas;
        Stack<PGSpriteFantasma> fantasmas;

        Song musicaFundo;

        public PGFantasmaMain(Game game)
            : base(game)
        {
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            InicializaSalas();

            musicaFundo = Game.Content.Load<Song>(@"Audio/Songs/Fantasma");
            MediaPlayer.Play(musicaFundo);

            base.LoadContent();
        }

        private void InicializaSalas()
        {
            PGSalasFantasma<TiposSaidas> construtorSalas = new PGSalasFantasma<TiposSaidas>(qtdeSalas, Game);
            fase = new List<EntityManager>(qtdeSalas);

            fase.Add(construtorSalas.ConstruirSalaFantasmaInicio(TiposSaidas.Proxima, mudaMapa_Triggered, gatilhoDialogo_Ativou));
            for (int i = 1; i < qtdeSalas - 1; i++)
                fase.Add(construtorSalas.ConstruirSalaFantasmaMeio(TiposSaidas.Volta, TiposSaidas.Proxima, mudaMapa_Triggered, gatilhoDialogo_Ativou));
            fase.Add(construtorSalas.ConstruirSalaFantasmaFim(TiposSaidas.Volta, mudaMapa_Triggered, gatilhoDialogo_Ativou));

            foreach (var sala in fase)
                sala.Initialize();

            iteraSalas = 0;
            fase[iteraSalas].WakeUp();
            Mapa = fase[iteraSalas];

            fantasmas = construtorSalas.FantasmasLigados;
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            Mapa = fase[iteraSalas];


            if (fantasmas != null && fantasmas.Count < 1)
            {
                fantasmas = null;
                ConversaFimFase();
            }

            base.Update(gameTime);
        }

        protected override void jogador_EnergiaAcabou(object sender, EventArgs e)
        {
            MediaPlayer.Stop();
            EstadoFase = EstadosFase.JogadorMorreu;
            OnFimFase(this, EventArgs.Empty);

            base.jogador_EnergiaAcabou(sender, e);
        }

        private void gatilhoDialogo_Ativou(object sender, EventArgs e)
        {
            PGGatilhoJogador gj = sender as PGGatilhoJogador;

            switch (gj.Id)
            {
                case 0:
                    ConversaFantasmaInicio();
                    break;

                case 1:
                    ConversaFantasmaSalaFim();
                    break;

                default:
                    throw new NotImplementedException();
            }

            gj.Alive = false;
        }

        private void mudaMapa_Triggered(object sender, MudaMapaEventArgs<TiposSaidas> e)
        {
            switch (e.Id)
            {
                case TiposSaidas.Volta:
                    iteraSalas--;
                    break;

                case TiposSaidas.Proxima:
                    iteraSalas++;
                    break;
            }

            fase[iteraSalas].WakeUp();
        }

        private void ConversaFimFase()
        {
            DialogBox<byte> db = Game.Services.GetService(typeof(DialogBox<byte>)) as DialogBox<byte>;
            db.AddSpeech("Fantasma Magicursivo Original: \"Oh nao! Nao e' possivel! Fui derrotado por um mero kobold pescador de peixes!\"");
            db.AddSpeech("Fantasma Magicursivo Original: \"Pelo menos ele nunca vai conseguir libertar os seus amigos e familiares da maldicao...\"");
            db.AddSpeech("Fantasma Magicursivo Original: \"Mwahuahuahua... hohohohoho... hahahahaha...\"");
            db.AddSpeech("Fantasma Magicursivo Original: \"Gaaaaaahhhh...\"");
            db.WakeUp();

            db.Finished += new EventHandler(db_Finished);
            EstadoFase = EstadosFase.Pausado;
        }

        void db_Finished(object sender, EventArgs e)
        {
            MediaPlayer.Stop();
            EstadoFase = EstadosFase.FaseCompletada;
            OnFimFase(this,EventArgs.Empty);
        }

        private void ConversaFantasmaSalaFim()
        {
            DialogBox<byte> db = Game.Services.GetService(typeof(DialogBox<byte>)) as DialogBox<byte>;
            db.AddSpeech("Magicursivo: \"O que? Um kobold esta livre e ainda foi capaz de chegar ate aqui armado? Malditos fantasmas, soberbos e estupidos...\"");
            db.AddSpeech("Magicursivo: \"Mas nao tem problema, eu mesmo acabo com voce. Prepare-se!\"");
            db.AddSpeech("Atalph:\"A sua vida nao sera tao facil assim! Vou vence-lo e depois derrotarei suas copias, uma a uma.\"");
            db.WakeUp();

            EstadoFase = EstadosFase.Pausado;
        }

        private void ConversaFantasmaInicio()
        {
            DialogBox<byte> db = Game.Services.GetService(typeof(DialogBox<byte>)) as DialogBox<byte>;
            db.AddSpeech("Atalph: \"Mas o que e' isso???\"");
            db.AddSpeech("O espanto descuidado de Atalph alerta o estranho ser para a sua presenca.\"");
            db.AddSpeech("Fantasma: \"Ora ora, se nao e' um kobold fugitivo voltando para conferir seus ultimos segundos de vida! Nao se preocupe, kobold. O processo de revitalizacao 'Magicursivo' do meu espirito esta' quase no fim.\"");
            db.AddSpeech("Fantasma: \"Com a energia dos seus conterraneos que os estupidos castursos capturaram, eu estou criando varias copias de mim mesmo.\"");
            db.AddSpeech("Fantasma: \"Hahahahahahaha. Alias, neste momento eu mesmo sou uma copia! E enquanto eu tiver copias de mim mesmo, serei imortal.\"");
            db.AddSpeech("Atalph: \"Imortal? Mas voce ja nao e' um fantasma?\"");
            db.AddSpeech("Fantasma: \"Kobold tolo! Fantasmas nao possuem energia fisica, nao podemos sobreviver naturalmente.\"");
            db.AddSpeech("Fantasma: \" Mas usando a energia de seus amigos eu criei um fantasma magicursivo superior, capaz de se dividir em dois. E a cada vez que ele se divide, todos os outros fantasmas se tornam mais reais.\"");
            db.AddSpeech("Fantasma: \"E ainda por cima, um dos dois novos fantasmas e' um fantasma magicursivo. E pra completar a festa, os fantasmas comuns sao invenciveis enquanto o magicursivo existir!\"");
            db.AddSpeech("Fantasma: \"E, se por acaso o magicursivo for destruido, o ultimo fantasma gerado dele se torna um novo dele! Ou seja, para nos vencer todos, voce tem que nos destruir na ordem certa em que fomos criados.\"");
            db.AddSpeech("Fantasma: \"O processo e' tao complicado que eu nem me importo de explica-lo a voce, um simples e ignorante kobold... Mesmo porque voce nao vai escapar de mim com vida!\"");
            db.AddSpeech("Atalph: \"E' o que veremos!\"");
            db.AddSpeech("Jogador, nao tente enfrentar esse fantasma agora. Procure pelo problema base, aquele que voce e' capaz de resolver primeiro.\"");
            db.WakeUp();

            EstadoFase = EstadosFase.Pausado;
        }
    }
}